package com.jilefojing.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import com.jilefojing.beans.data.enums.ResponseEnum;
import com.jilefojing.beans.enums.ItemTypeEnumForSource;
import com.jilefojing.beans.enums.PlatformEnum;
import com.jilefojing.beans.enums.PlatformEnumForPublish;
import com.jilefojing.beans.enums.ProgressStatusForSource;
import com.jilefojing.beans.enums.StatusEnumForPublish;
import com.jilefojing.beans.exception.UserContextException;
import com.jilefojing.beans.pojos.Recommend;
import com.jilefojing.beans.pojos.base.BasePo;
import com.jilefojing.beans.pojos.enhanced.EnhancedRecommend;
import com.jilefojing.beans.pojos.enhanced.EnhancedUser;
import com.jilefojing.beans.pojos.enhanced.base.BaseEnhanced;
import com.jilefojing.beans.query.RecommendQuery;
import com.jilefojing.beans.vo.Order;
import com.jilefojing.beans.vo.Pagination;
import com.jilefojing.beans.vo.UploadFile;
import com.jilefojing.context.beans.vo.UserContext;
import com.jilefojing.dao.IRecommendDao;
import com.jilefojing.qiniu.beans.enums.BucketEnum;
import com.jilefojing.qiniu.beans.enums.BucketEnum.BucketEnumExtral_SourceEnum;
import com.jilefojing.service.IEVideoService;
import com.jilefojing.service.IRecommendService;
import com.jilefojing.service.ISourceService;
import com.jilefojing.service.IUserService;
import com.jilefojing.service.base.impl.BaseService;
import com.jilefojing.util.Detect;
import com.jilefojing.util.QiniuUtil;

/**
 * 
 * @author 作者 jgshun
 * @date 创建时间 2016年07月19日 17时57分48秒
 */
@Service
public class RecommendService extends BaseService<Recommend> implements IRecommendService {
	private static final Logger _LOGGER = LoggerFactory.getLogger(RecommendService.class);

	@Autowired
	private IRecommendDao recommendDao;
	@Autowired
	private IEVideoService eVideoService;
	@Autowired
	private IUserService userService;
	@Autowired
	private ISourceService sourceService;
	@Autowired
	private ApplicationContext applicationContext;

	@Override
	public Pagination<EnhancedRecommend> getPagination(RecommendQuery recommendQuery, Pagination<EnhancedRecommend> pagination, UserContext userContext) {
		@SuppressWarnings("unchecked")
		Pagination<Recommend> recommendPagination = recommendDao.getPagination(recommendQuery, pagination.copy());
		pagination.setCount(recommendPagination.getCount());

		if (!Detect.notEmpty(recommendPagination.getItems())) {
			return pagination;
		}
		List<EnhancedRecommend> enhancedRecommends = this.conventRecommends2EnhancedRecommends(recommendPagination.getItems());

		this.appendEnhancedCommons(enhancedRecommends, userContext);

		pagination.setItems(enhancedRecommends);
		return pagination;
	}

	@Override
	public List<EnhancedRecommend> appendEnhancedCommons(List<? extends BaseEnhanced> enhancedItems, UserContext userContext) {
		@SuppressWarnings("unchecked")
		List<EnhancedRecommend> enhancedRecommends = (List<EnhancedRecommend>) enhancedItems;
		this.appendEnhancedItems2EnhancedRecommends(enhancedRecommends, userContext);
		this.appendEnhancedUsers2EnhancedRecommends(enhancedRecommends, userContext);
		return enhancedRecommends;
	}

	@Override
	public List<EnhancedRecommend> conventRecommends2EnhancedRecommends(List<Recommend> recommends) {
		List<EnhancedRecommend> enhancedRecommends = new ArrayList<EnhancedRecommend>();
		for (Recommend _Recommend : recommends) {
			if (Detect.notEmpty(_Recommend.getCoverUrl()) && !_Recommend.getCoverUrl().startsWith(SCHEMA)) {
				_Recommend.setCoverUrl(QiniuUtil.getImagesDomain() + _Recommend.getCoverUrl());
			}
			enhancedRecommends.add(new EnhancedRecommend(_Recommend));
		}

		return enhancedRecommends;
	}

	@Override
	public List<EnhancedRecommend> appendEnhancedItems2EnhancedRecommends(List<EnhancedRecommend> enhancedRecommends, UserContext userContext) {
		Map<Class<? extends BasePo>, List<Long>> itemsMap = new HashMap<Class<? extends BasePo>, List<Long>>();

		for (EnhancedRecommend _EnhancedRecommend : enhancedRecommends) {
			List<Long> itemIds = itemsMap.get(_EnhancedRecommend.getItemType().getItemClass());
			if (!Detect.notEmpty(itemIds)) {
				itemIds = new ArrayList<Long>();
				itemsMap.put(_EnhancedRecommend.getItemType().getItemClass(), itemIds);
			}
			itemIds.add(_EnhancedRecommend.getEnhancedItem().getDynamicId());
		}
		Set<Entry<Class<? extends BasePo>, List<Long>>> itemsEntry = itemsMap.entrySet();
		for (Entry<Class<? extends BasePo>, List<Long>> _Entry : itemsEntry) {
			if (Detect.notEmpty(_Entry.getValue())) {
				this.appendEnhancedItems2EnhancedRecommends(_Entry, enhancedRecommends, userContext);
			}
		}
		return enhancedRecommends;
	}

	@SuppressWarnings("unchecked")
	private void appendEnhancedItems2EnhancedRecommends(Entry<Class<? extends BasePo>, List<Long>> entry, List<EnhancedRecommend> enhancedRecommends, UserContext userContext) {
		try {
			// WebApplicationContext webApplicationContext =
			// ContextLoader.getCurrentWebApplicationContext();

			Class serviceClass = Class.forName("com.jilefojing.service.I" + entry.getKey().getSimpleName() + "Service");
			Object interfaceImpl = applicationContext.getBean(serviceClass);

			List<BaseEnhanced> enhancedItems = null;
			for (Method _Method : serviceClass.getMethods()) {
				if (_Method.getName().equals("getEnhanceds")) {
					// enhancedItems = (List<BaseEnhanced>)
					// _Method.invoke(webApplicationContext.getBean(serviceClass),
					// entry.getValue(), userContext);
					enhancedItems = (List<BaseEnhanced>) _Method.invoke(interfaceImpl, entry.getValue(), userContext);
					break;
				}
			}

			for (EnhancedRecommend _EnhancedRecommend : enhancedRecommends) {
				for (BaseEnhanced _BaseEnhanced : enhancedItems) {
					if (_EnhancedRecommend.getItemType().getEnhancedItemClass() == _BaseEnhanced.getClass() && _EnhancedRecommend.getEnhancedItem().getDynamicId() == _BaseEnhanced.getDynamicId()) {
						_EnhancedRecommend.setEnhancedItem(_BaseEnhanced);
						break;
					}
				}
			}

		} catch (ClassNotFoundException | BeansException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
			_LOGGER.error("获取资源Service出错", e1);
		}

	}

	@Override
	public List<EnhancedRecommend> appendEnhancedUsers2EnhancedRecommends(List<EnhancedRecommend> enhancedRecommends, UserContext userContext) {
		this.appendEnhancedCreateUser2EnhancedRecommends(enhancedRecommends, userContext);
		return enhancedRecommends;
	}

	private void appendEnhancedCreateUser2EnhancedRecommends(List<EnhancedRecommend> enhancedRecommends, UserContext userContext) {
		List<Long> userIds = new ArrayList<Long>();
		for (EnhancedRecommend _EnhancedRecommend : enhancedRecommends) {
			userIds.add(_EnhancedRecommend.getEnhancedUser().getId());
		}

		List<EnhancedUser> enhancedUsers = userService.getEnhancedUsers(userIds);
		if (Detect.notEmpty(enhancedUsers)) {
			for (EnhancedRecommend _EnhancedRecommend : enhancedRecommends) {
				for (EnhancedUser _EnhancedUser : enhancedUsers) {
					if (_EnhancedRecommend.getEnhancedUser().getId() == _EnhancedUser.getId()) {
						_EnhancedRecommend.setEnhancedUser(_EnhancedUser);
						break;
					}
				}
			}
		}

	}

	@Override
	public Pagination<EnhancedRecommend> getPaginationForActive(PlatformEnum platform, ItemTypeEnumForSource itemType, Pagination<EnhancedRecommend> pagination, UserContext userContext) {
		List<PlatformEnumForPublish> platforms = new ArrayList<PlatformEnumForPublish>();
		platforms.add(PlatformEnumForPublish.ALL);
		if (platform == PlatformEnum.ANDROID) {
			platforms.add(PlatformEnumForPublish.ANDROID_AND_IOS);
			platforms.add(PlatformEnumForPublish.ANDROID);
		} else if (platform == PlatformEnum.IPHONE) {
			platforms.add(PlatformEnumForPublish.ANDROID_AND_IOS);
			platforms.add(PlatformEnumForPublish.IOS);
		} else if (platform == PlatformEnum.PC) {
			platforms.add(PlatformEnumForPublish.WEB_AND_WAP);
			platforms.add(PlatformEnumForPublish.WEB);
		} else if (platform == PlatformEnum.WAP) {
			platforms.add(PlatformEnumForPublish.WEB_AND_WAP);
			platforms.add(PlatformEnumForPublish.WAP);
		}

		RecommendQuery recommendQuery = new RecommendQuery();
		recommendQuery.setStatuses(Arrays.asList(new StatusEnumForPublish[] { StatusEnumForPublish.ALREADY_RELEASED }));
		recommendQuery.setPlatforms(platforms);
		Date nowDate = new Date();
		recommendQuery.setEqualAndAfterStartTime(nowDate);
		recommendQuery.setEqualAndBeforEndTime(nowDate);
		if (itemType != null) {
			recommendQuery.setItemTypes(Arrays.asList(new ItemTypeEnumForSource[] { itemType }));
		}
		if (!Detect.notEmpty(pagination.getItems())) {
			pagination.addOrder(new Order(Recommend.COLUMN_SORT, Order.ORDER_DESC));
		}
		pagination = this.getPagination(recommendQuery, pagination, userContext);
		return pagination;
	}

	@Override
	public Recommend update(Recommend recommend, UserContext userContext) throws UserContextException {
		Recommend dbRecommend = recommendDao.getById(recommend.getId());
		if (dbRecommend == null) {
			throw new UserContextException("[此推荐资源已不存在]");
		}
		dbRecommend.setInfo(recommend.getInfo());
		dbRecommend.setSort(recommend.getSort());
		dbRecommend.setPlatform(recommend.getPlatform());
		dbRecommend.setStartTime(recommend.getStartTime());
		dbRecommend.setEndTime(recommend.getEndTime());
		return recommendDao.updateByPrimaryKey(dbRecommend);
	}

	@Override
	public void deleteById(long id, UserContext userContext) throws UserContextException {
		this.deleteByIds(Arrays.asList(new Long[] { id }), userContext);
	}

	@Override
	public void deleteByIds(List<Long> ids, UserContext userContext) {
		recommendDao.deleteByIds(ids, Recommend.FIELD_ID, Recommend.class);
	}

	@Override
	public Recommend add(Recommend recommend, UploadFile coverFile, UserContext userContext) throws UserContextException {
		this.checkAdd(ItemTypeEnumForSource.getItemTypeEnumByCode(recommend.getItemType()), recommend.getItemId(), userContext);

		Date now = new Date();

		recommend.setId(null);

		BaseEnhanced enhancedItem = sourceService.getEnhancedItem(ItemTypeEnumForSource.getItemTypeEnumByCode(recommend.getItemType()), recommend.getItemId(), userContext);
		recommend.setStatus(((StatusEnumForPublish) enhancedItem.get("getStatus")).getCode());
		recommend.setProgressStatus(((ProgressStatusForSource) enhancedItem.get("getProgressStatus")).getCode());

		recommend.setCreateTime(now);
		recommend.setUpdateTime(now);
		if (recommend.getStartTime() == null) {
			recommend.setStartTime(now);
		}
		if (recommend.getEndTime() == null) {
			recommend.setEndTime(new GregorianCalendar(2999, 11, 31, 23, 59, 59).getTime());
		}
		recommend.setCreateUser(userContext.getUserId());
		if (recommend.getPlatform() == null) {
			recommend.setPlatform(PlatformEnumForPublish.ALL.getCode());
		}
		if (coverFile != null) {
			recommend.setCoverUrl(QiniuUtil.upload(coverFile, BucketEnum.IMG, BucketEnumExtral_SourceEnum.VIDEO_COVER));
		}

		if (recommend.getSort() == null) {
			recommend.setSort(0D);
		}

		if (recommend.getStartTime().after(recommend.getEndTime())) {
			throw new UserContextException("[开始时间不能大于结束时间]");
		}

		return recommendDao.save(recommend);
	}

	// public List<Recommend> add(List<Recommend> recommends, UserContext
	// userContext) {
	// Map<Short, List<Long>> itemMaps = new HashMap<Short, List<Long>>();
	//
	// for (Recommend _Recommend : recommends) {
	// if (itemMaps.get(_Recommend.getItemType()) == null) {
	// itemMaps.put(_Recommend.getItemType(), new ArrayList<Long>());
	// }
	// itemMaps.get(_Recommend.getItemType()).add(_Recommend.getItemId());
	// }
	//
	// Set<Entry<Short, List<Long>>> itemEntrys = itemMaps.entrySet();
	// for (Entry<Short, List<Long>> _itemEntry : itemEntrys) {
	// this.checkAdd(ItemTypeEnumForSource.getItemTypeEnumByCode(_itemEntry.getKey()),
	// _itemEntry.getValue());
	// }
	//
	// List<Recommend> records = new ArrayList<Recommend>();
	//
	// // public static final String FIELD_PLATFORM = "platform";
	// // public static final String FIELD_COVERURL = "coverUrl";
	// // public static final String FIELD_INFO = "info";
	// // public static final String FIELD_SORT = "sort";
	//
	// Date now = new Date();
	// for (Recommend _Recommend : recommends) {
	// _Recommend.setId(null);
	// _Recommend.setStatus(StatusEnumForRecommend.ALREADY_RECOMMEND.getCode());
	// _Recommend.setCreateTime(now);
	// _Recommend.setUpdateTime(now);
	// if (_Recommend.getStartTime() == null) {
	// _Recommend.setStartTime(now);
	// }
	// if (_Recommend.getEndTime() == null) {
	// _Recommend.setEndTime(new GregorianCalendar(2999, 12, 31, 23, 59,
	// 59).getTime());
	// }
	// _Recommend.setCreateUser(userContext.getUserId());
	// if (_Recommend.getPlatform() == null) {
	// _Recommend.setPlatform(PlatformEnumForPublish.ALL.getCode());
	// }
	// }
	//
	// return recommendDao.saveList(records);
	// }

	private void checkAdd(ItemTypeEnumForSource itemType, long itemId, UserContext userContext) throws UserContextException {
		this.checkAdd(itemType, Arrays.asList(new Long[] { itemId }), userContext);
	}

	private void checkAdd(ItemTypeEnumForSource itemType, List<Long> itemIds, UserContext userContext) throws UserContextException {
		List<EnhancedRecommend> dbEnhancedRecommends = this.getEnhancedRecommendsByItems(itemType, itemIds, userContext);

		if (Detect.notEmpty(dbEnhancedRecommends)) {
			StringBuilder tipBud = new StringBuilder();
			tipBud.append("[这些推荐已存在:");

			for (int i = 0; i < dbEnhancedRecommends.size(); i++) {
				EnhancedRecommend _EnhancedRecommend = dbEnhancedRecommends.get(0);
				tipBud.append(_EnhancedRecommend.getEnhancedItem().getString("getTitle"));
				if (i < dbEnhancedRecommends.size() - 1) {
					tipBud.append("_///_");
				}
			}
			tipBud.append("]");
			throw new UserContextException(tipBud.toString());
		}
		List<BaseEnhanced> enhancedItems = sourceService.getEnhancedItems(itemType, itemIds, userContext);
		if (!Detect.notEmpty(enhancedItems)) {
			throw new UserContextException(ResponseEnum.SOURCE_NOT_EXIST);
		}
		for (BaseEnhanced _enhancedItem : enhancedItems) {
			if ((StatusEnumForPublish) _enhancedItem.get("getStatus") != StatusEnumForPublish.ALREADY_RELEASED) {
				throw new UserContextException("[其中有无效资源]");
			}
		}
	}

	@Override
	public List<EnhancedRecommend> getEnhancedRecommendsByItems(ItemTypeEnumForSource itemType, List<Long> itemIds, UserContext userContext) {
		RecommendQuery recommendQuery = new RecommendQuery();
		recommendQuery.setItemTypes(Arrays.asList(new ItemTypeEnumForSource[] { itemType }));
		recommendQuery.setItemIds(itemIds);

		Pagination<EnhancedRecommend> pagination = new Pagination<EnhancedRecommend>(1, Integer.MAX_VALUE, false);
		pagination = this.getPagination(recommendQuery, pagination, userContext);
		return pagination.getItems();
	}

}
